﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Windows.Forms;
using RkLibs.Functions;
namespace RkLibs.Security
{
    /// <summary>
    /// 软件注册类
    /// </summary>
    public class SoftwareRegister
    {
        /// <summary>
        /// License所在的文件名
        /// </summary>
        private const string LICENSEFILENAME = "License.bin";
        /// <summary>
        /// 注册码随机次数
        /// </summary>
        private const int RND_TIMES = 2;
        /// <summary>
        /// License文件路径
        /// </summary>
        private string LicensePath;
        /// <summary>
        /// 主页网址
        /// </summary>
        private const string HOME_PAGE = "https://shop148743344.taobao.com/?spm=a230r.7195193.1997079397.2.gRMsB5";
        /// <summary>
        /// Host标识码
        /// </summary>
        public string HostIdentify{get;protected set;}
        /// <summary>
        /// 账户名称
        /// </summary>
        private string UserID;
        /// <summary>
        /// 软件名称
        /// </summary>
        public string SoftwareName { get; protected set; }
        /// <summary>
        /// 注册结果
        /// </summary>
        private RegisterResult _regResut;
        /// <summary>
        /// 注册结果
        /// </summary>
        public RegisterResult RegResult
        {
            get
            {
                InitRegState();
                return _regResut;
            }
        }
        /// <summary>
        /// 注册类构造函数
        /// 软件使用
        /// </summary>
        /// <param name="softwareName">软件名称枚举</param>
        public SoftwareRegister(SoftNameDef softwareName)
        {
            string BaseDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + softwareName + "\\";
            this.SoftwareName = softwareName.ToString();
            CommonFunction.CreateDirectory(BaseDir);
            LicensePath = BaseDir + LICENSEFILENAME;
            HostIdentify = GetHostDiskVolumeStr();
        }
        /// <summary>
        /// 注册类构造函数
        /// 注册机使用
        /// </summary>
        /// <param name="softwareName">字符串软件名</param>
        public SoftwareRegister(string softwareName)
        {
            this.SoftwareName = softwareName;
        }
        /// <summary>
        /// 获取注册码
        /// 注册机使用
        /// </summary>
        /// <param name="hostIdentify">机器码</param>
        /// <param name="userID">用户账户</param>
        /// <returns>注册码字符串</returns>
        public string GetRegStr(string hostIdentify, string userID)
        {
            string str = hostIdentify + userID + this.SoftwareName;
            str = RkMD5.GetMD5Hash(str, 32);
            str = RandmStr(str, RND_TIMES);
            return str;
        }
        /// <summary>
        /// 注册软件
        /// 软件使用
        /// </summary>
        /// <param name="userID">用户账户</param>
        /// <param name="regStr">注册码</param>
        public void RegisterSoftware(string userID, string regStr)
        {
            string str = string.Format("{0}_{1}", userID, regStr);
            SaveLicense(LicensePath,str);
        }
        /// <summary>
        /// 访问主页
        /// </summary>
        public void ShowHomePage()
        {
            System.Diagnostics.Process.Start(HOME_PAGE);
        }
        /// <summary>
        /// 初始化注册结果
        /// </summary>
        private void InitRegState()
        {
            string str = GetLicense(LicensePath);
            string[] ArrStr = str.Split('_');
            if (ArrStr.Length != 2)
            {
                _regResut = RegisterResult.FAILED;
                return;
            }
            this.UserID = ArrStr[0];
            string RegStr = ArrStr[1];
            if (IsValidRegStr(RegStr))
            {
                _regResut = RegisterResult.SUCCEED;
            }
            else
            {
                _regResut = RegisterResult.FAILED;
            }
        }
        /// <summary>
        /// 判断是否为有效注册码
        /// </summary>
        /// <param name="regStr">注册码</param>
        /// <returns>true：有效</returns>
        private bool IsValidRegStr(string regStr)
        {
            string str = DeRandmStr(regStr, RND_TIMES);
            string HostRegStr = GetHostRegStr();
            if (0 == string.Compare(str, HostRegStr))
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取机器码
        /// </summary>
        /// <returns></returns>
        private string GetHostRegStr()
        {
            string str = this.HostIdentify + this.UserID + this.SoftwareName;
            str = RkMD5.GetMD5Hash(str, 32);
            return str;
        }
        /// <summary>
        /// 获取目标Host磁盘容量字符串
        /// </summary>
        /// <returns>磁盘容量字符串</returns>
        public static string GetHostDiskVolumeStr()
        {
            string str = "";
            DriveInfo[] DrvInfo = DriveInfo.GetDrives();
            int ChrNum = DrvInfo.Length < 3 ? 16 : 32;
            try
            {
                foreach (var drv in DrvInfo)
                {
                    //利用十六进制链接每一个盘符的字符串
                    if (drv.TotalSize > 0)
                    {
                        str += RkMD5.GetMD5Hash(drv.TotalSize.ToString("X"), ChrNum);
                    }
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return str;
        }
        #region 字符串随机和恢复
        /// <summary>
        /// 修正位数
        /// </summary>
        private const int AmendNum = 20;
        /// <summary>
        /// 随机化字符串
        /// </summary>
        /// <param name="_str">需要随机的字符串</param>
        /// <returns>随机后的字符串</returns>
        public static string RandmStr(string _str)
        {
            string strRet = "";
            //ArrayList chrList = new ArrayList();
            Dictionary<int, string> chrDic = new Dictionary<int, string>();
            chrDic.Clear();
            for (int i = 0; i < _str.Length; i++)
            {
                chrDic.Add(i, _str.Substring(i, 1));
            }
            while (chrDic.Count > 0)
            {
                Dictionary<int, string>.KeyCollection Tmp = chrDic.Keys;
                int iTmp = Environment.TickCount % Tmp.Count;
                int keyTmp;
                string ItemTmp;
                keyTmp = Tmp.ElementAt(iTmp);//获取位置
                chrDic.TryGetValue(keyTmp, out ItemTmp);
                strRet += string.Format("{0:X3}{1}", keyTmp + AmendNum, ItemTmp);
                chrDic.Remove(keyTmp);
            }
            return strRet;
        }
        public static string RandmStr(string _str, int rndTimes)
        {
            string str = _str;
            while ((rndTimes--) > 0)
            {
                str = RandmStr(str);
            }
            return str;
        }
        /// <summary>
        /// 恢复随机字符串
        /// </summary>
        /// <param name="_str">随机后的字符串</param>
        /// <returns>原始字符串</returns>
        public static string DeRandmStr(string _str)
        {
            int ArrIndex;
            int itemLen = 4;
            string strRet = "";
            string[] chrArr = new string[(int)(_str.Length / itemLen)];
            for (int i = 0; i < _str.Length; i += itemLen)
            {
                try
                {
                    ArrIndex = Convert.ToInt32(_str.Substring(i, itemLen - 1), 16) - AmendNum;
                    if (ArrIndex >= chrArr.GetLowerBound(0) && ArrIndex <= chrArr.GetUpperBound(0))
                    {
                        chrArr[ArrIndex] = _str.Substring(i + itemLen - 1, 1);
                    }
                }
                catch
                {

                }
            }
            strRet = string.Join("", chrArr);
            chrArr = null;
            return strRet;
        }
        public static string DeRandmStr(string _str, int rndTimes)
        {
            string str = _str;
            while ((rndTimes--) > 0)
            {
                str = DeRandmStr(str);
            }
            return str;
        }
        #endregion
        #region 注册码保存获取

        /// <summary>
        /// 获取保存在本机的注册码
        /// </summary>
        /// <returns></returns>
        public static string GetLicense(string licensePath)
        {
            string strRet = "";
            if (File.Exists(licensePath))
            {
                using (FileStream FS = new FileStream(licensePath, FileMode.OpenOrCreate, FileAccess.Read))
                {
                    using (BinaryReader br = new BinaryReader(FS))
                    {
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        byte[] buffer = br.ReadBytes((int)br.BaseStream.Length);
                        strRet = Encoding.Unicode.GetString(buffer);
                        br.Close();
                        FS.Close();
                    }
                }
            }
            return DES.DecryptString(strRet);
        }
        /// <summary>
        /// 保存注册码
        /// </summary>
        /// <param name="license"></param>
        public static void SaveLicense(string licensePath, string license)
        {
            using (FileStream FS = new FileStream(licensePath, FileMode.Create, FileAccess.Write))
            {
                using (BinaryWriter bw = new BinaryWriter(FS))
                {
                    byte[] buffer = Encoding.Unicode.GetBytes(DES.EncryptString(license));
                    bw.BaseStream.Seek(0, SeekOrigin.Begin);
                    bw.Write(buffer);
                    bw.Close();
                    FS.Close();
                }
            }
        }
        #endregion

    }
}
